﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StyleMVVM.DependencyInjection.Impl
{
	internal sealed class ExportCollection : IExportCollection
	{
		private IDependencyInjectionContainer container;
		private object lockObject = new object();
		private volatile ReadOnlyCollection<IExportStrategy> exportStrategies;
		private Comparison<IExportStrategy> comparison;
 
		internal ExportCollection(IDependencyInjectionContainer container, Comparison<IExportStrategy> comparison)
		{
			this.container = container;
			this.comparison = comparison;
		}

		public void AddExportStrategy(IExportStrategy exportStrategy)
		{
			lock (lockObject)
			{
				List<IExportStrategy> newList = new List<IExportStrategy>{ exportStrategy};

				if (exportStrategies != null)
				{
					newList.AddRange(exportStrategies);
				}

				newList.Sort(comparison);

				newList.Reverse();

#if NETFX_CORE
				exportStrategies = new ReadOnlyCollection<IExportStrategy>(newList);
#else
				exportStrategies = newList.AsReadOnly();
#endif
			}
		}

		public void RemoveExportStrategy(IExportStrategy exportStrategy)
		{
			if (exportStrategies == null || exportStrategies.Count == 0)
			{
				return;
			}

			lock (lockObject)
			{
				List<IExportStrategy> newList = new List<IExportStrategy>(exportStrategies);

				newList.Remove(exportStrategy);

				newList.Sort(comparison);

				newList.Reverse();

#if NETFX_CORE
				exportStrategies = new ReadOnlyCollection<IExportStrategy>(newList);
#else
				exportStrategies = newList.AsReadOnly();
#endif
			}
		}

		public IEnumerable<IExportStrategy> ExportStrategies()
		{
			return exportStrategies;
		}

		public object ActivateExport(IInjectionContext injectionContext, object[] constructorParams)
		{
			var tempList = exportStrategies;

			for (int i = 0; i < tempList.Count; i++)
			{
				IExportStrategy strategy = tempList[i];

				if (strategy.MeetsConditions(container, injectionContext))
				{
					return strategy.Activate(injectionContext, constructorParams);
				}
			}

			return null;
		}
	}
}
